Skip to content

S09-05 Webpack5-Gulp、Rollup、Vite

[TOC]

自动化工具Gulp4

Gulp API

gulp

  • 任务组合
  • gulp.series()(task1, task2, ...),按顺序执行任务。
    • task1...string | function,需要按顺序执行的任务名或任务函数。
    • 返回:
    • tasksfunction,执行任务的函数。
  • gulp.parallel()(task1, task2, ...),并行执行任务。
    • task1...string | function,需要按顺序执行的任务名或任务函数。
    • 返回:
    • tasksfunction,执行任务的函数。
  • 文件操作
  • gulp.src()(glob, options?),读取文件并返回流。
    • globstring | string[],文件模式,支持 glob 匹配。
    • options?{base,cwd},可选配置,如 basecwd
    • 返回:
    • streamNodeJS.ReadWriteStream,读取流。
  • gulp.dest()(path, options?),将流写入目标目录。
    • pathstring,目标目录。
    • options?{base,cwd},可选配置,如 basecwd
    • 返回:
    • streamNodeJS.ReadWriteStream,可写流。
  • stream.pipe()(transform),将流传递给下一个处理步骤。常用于插件链式操作。
    • transformstream.Transform,变换流,如插件。
  • gulp.watch()(glob, tasks),监视文件变化并重新运行任务。
    • globstring | string[],监视的文件模式。
    • tasksstring | string[] | function,任务名或任务函数。
    • 返回:
    • gulp-watch:``,监视流。

gulp-babel

gulp-babel:是一个 Gulp 插件,用于将 Babel 转换的功能集成到 Gulp 流程中。

API:

  • babel()({plugins?, presets?}),用于将 Babel 转换功能集成到 Gulp 流程中。
    • plugins?array,babel插件(plugins)的配置对象。
    • presets?array,babel预设(presets)的配置对象。
    • 返回:
    • streamStream,返回一个 Gulp 流对象

gulp-terser

gulp-terser:是一个用于在 Gulp 构建流程中集成 Terser 的插件,Terser 是一个用于 JavaScript 文件压缩和混淆的工具。

API:

  • terser()({mangle, compress, output}),接收配置选项来控制压缩行为。
    • mangleobject,混淆选项
      • toplevelboolean,是否混淆顶级变量和函数
      • keep_fnamesboolean,保留函数名
      • keep_cnamesboolean,保留类名
    • compressobject,压缩选项
      • drop_consoleboolean,是否删除console
      • arrowsboolean,是否转换成箭头函数
      • argumentsboolean,是否将arguments[index]转成对应的形参名称
      • dead_codeboolean,是否移除不可达的代码
      • unusedboolean,是否移除未使用过的函数
    • outputobject,输出选项
      • commentsboolean,是否保留注释
    • 返回:
    • streamStream,返回一个 Gulp 流对象

gulp-htmlmin

gulp-htmlmin:是一个用于在使用 Gulp 构建工具时对 HTML 文件进行压缩的插件。它基于 html-minifier 库。

API:

  • htmlmin()(options),用于压缩 HTML 文件

    • options{collapseWhitespace,...},配置对象,用于指定各种压缩选项。与htmlWebpackPlugins插件的minify选项一致。

      • collapseWhitespace: 去除空格
      • removeComments: 删除注释
      • removeEmptyAttributes: 删除空属性
      • removeRedundantAttributes: 删除多余的属性
      • removeScriptTypeAttributes: 删除 script 标签的 type 属性
      • removeStyleLinkTypeAttributes: 删除 style 和 link 标签的 type 属性
      • useShortDoctype: 使用短的 doctype 声明
      • minifyJS: 压缩内嵌的 JavaScript 代码
      • minifyCSS: 压缩内嵌的 CSS 代码
    • 返回:

    • streamStream,返回一个Stream对象,可以将它与其他 Gulp 插件链式调用,以便在管道中处理文件。

    • js
      const gulp = require('gulp');
      const htmlmin = require('gulp-htmlmin');
      const rename = require('gulp-rename');
      
      gulp.task('minify', () => {
        return gulp.src('src/*.html')
          .pipe(htmlmin({ collapseWhitespace: true }))
          .pipe(rename({ suffix: '.min' }))
          .pipe(gulp.dest('dist'));
      });

gulp-less

gulp-less:是一个用于 Gulp 的 LESS 插件,主要用于将 LESS 文件编译成 CSS 文件。

API:

  • less()(options?),用于将 LESS 文件编译成 CSS 文件。

    • options?{paths?, plugins?},编译选项。
      • paths?string[],用于 @import 指令的路径数组。
      • plugins?string[],LESS 插件数组。
    • 返回:
    • streamStream,返回一个Stream对象,可以将它与其他 Gulp 插件链式调用,以便在管道中处理文件。
  • js
    var less = require('gulp-less');
    var path = require('path');
    
    gulp.task('less', function () {
      return gulp.src('./less/**/*.less')
        .pipe(less({
          paths: [ path.join(__dirname, 'less', 'includes') ]
        }))
        .pipe(gulp.dest('./public/css'));
    });

gulp-inject

gulp-inject:是一个用于 Gulp 的插件,可以将样式表JavaScriptWeb 组件的引用注入到 HTML 文件中,避免手动编辑 index.html 文件。

API:

  • inject()(source, options?),用于将文件路径注入到 HTML 文件中。

    • sourcestream | string,要注入的文件流或文件路径。通常这是一个 Gulp 任务生成的流,例如 gulp.src('path/to/files/*.js')

    • options?object,可选配置对象,用于定制注入行为。

      • starttag?string默认:<!-- inject:{ {ext} } -->,注入内容的开始标记。
      • endtag?string默认:<!-- endinject -->,注入内容的结束标记。
      • transform?(filepath) => void,自定义处理注入内容的函数。
      • ignorePath?string | string[]默认:null,用于忽略路径中的部分字符串,以便生成相对路径。
      • addRootSlash?boolean默认:true,是否在路径前添加根斜杠。
      • relative?boolean默认:false,是否使用相对路径。
    • 返回:

    • streamStream,返回一个Stream对象,可以将它与其他 Gulp 插件链式调用,以便在管道中处理文件。

    • js
      const inject = require('gulp-inject');
      const gulp = require('gulp');
      
      gulp.task('inject', function () {
        const sources = gulp.src(['src/**/*.js', 'src/**/*.css'], {read: false});
        return gulp.src('src/index.html')
          .pipe(inject(sources, {
            starttag: '<!-- inject:{{ext}} -->',
            endtag: '<!-- endinject -->',
            transform: function (filepath) {
              return '<script src="' + filepath + '"></script>';
            }
          }))
          .pipe(gulp.dest('dist'));
      });

browser-sync

browser-sync:是一个用于前端开发的工具,可以帮助你实时刷新浏览器页面。它会监视文件的变化,自动刷新浏览器,提升开发效率。

API:

  • browserSync.init()(config, callback?),初始化 BrowserSync 的函数,它接受一个配置对象来定义服务器的行为和特性。

    • configobject,定义服务器的行为和特性的配置对象。

      • server{baseDir},用于设置静态文件服务器的根目录。
      • filesstring[],用于监视文件变化,并自动刷新浏览器。
      • portnumber,指定服务器的端口号。
      • openboolean,是否在启动时自动打开浏览器。
      • proxystring,用于代理现有的服务器(如本地开发的服务器)。
    • callback?function,初始化 BrowserSync 完毕后回调的函数。

    • js
      const gulp = require('gulp');
      const browserSync = require('browser-sync').create();
      
      gulp.task('serve', function() {
          browserSync.init({
              server: "./app"
          });
      
          gulp.watch("app/*.html").on('change', browserSync.reload);
          gulp.watch("app/css/*.css").on('change', browserSync.reload);
          gulp.watch("app/js/*.js").on('change', browserSync.reload);
      });
      
      gulp.task('default', gulp.series('serve'));

概述

什么是Gulp

什么是 Gulp?

  • A toolkit to automate & enhance your workflow;

  • 一个工具包,可以帮你自动化和增强工作流

image-20240229144108688

Gulp和Webpack

gulp 的核心理念是task runner

  • 可以定义自己的一系列任务,等待任务被执行;

  • 基于文件 Stream 的构建流;

  • 我们可以使用 gulp 的插件体系来完成某些任务;

webpack 的核心理念是module bundler

  • webpack 是一个模块化的打包工具;

  • 可以使用各种各样的 loader 来加载不同的模块;

  • 可以使用各种各样的插件在 webpack 打包的生命周期完成其他的任务;

gulp相对于webpack的优缺点:

  • gulp 相对于 webpack 思想更加的简单、易用,更适合编写一些自动化的任务

  • 但是目前对于大型项目(Vue、React、Angular)并不会使用 gulp 来构建,比如默认 gulp 是不支持模块化的;

基本使用

Gulp基本使用

依赖包: gulp:是一个流行的任务自动化工具,主要用于前端开发中的构建和优化工作。它基于 Node.js,使用流(streams)来处理文件,使得构建过程更高效。

1、安装gulp

sh
# 全局安装
npm install gulp -g

# 局部安装
npm install gulp

2、编写 gulpfile.js 文件,在其中创建一个任务。

注意: gulpfile.js 文件名是固定的。

image-20240229144147215

3、执行 gulp 命令

sh
npx gulp foo

4、返回结果

image-20240907154510955

5、gulp任务函数需要执行callback回调,任务才能结束

image-20240907154616833

image-20240907154643447

6、异步任务

image-20240907155327167

语法

创建任务

每个gulp任务都是一个异步的JS函数

Gulp任务结束条件

  • 函数接受一个 callback 作为参数,调用 callback 函数那么任务就会结束。
  • 返回streampromiseevent emitterchild processobservable 类型的函数。

任务可以是 public 或者 private 类型的:

  • 公开任务(Public tasks) 从 gulpfile 中被导出(module.exports),可以通过 gulp 命令直接调用;

  • 私有任务(Private tasks) 被设计为在内部使用,通常作为 series() 或 parallel() 组合的组成部分;

补充:gulp4 之前, 注册任务时通过 gulp.task 的方式进行注册的

image-20240229144158781

默认任务

默认任务:

  • 可以在 gulpfile.js 中使用 exports.default 来定义默认任务。
  • 默认任务可以包含其他任务的组合,使用 series(顺序执行)或 parallel(并行执行)方法。
  • 当运行 gulp 命令时,Gulp 会自动执行这个默认任务。
js
exports.default = (callback) => void
module.exports.default = (callback) => void

示例:

1、我们可以编写一个默认任务

image-20240907155850759

image-20240907155803274

2、执行gulp命令

sh
npx gulp

任务组合

  • gulp.series()(task1, task2, ...),按顺序执行任务。
    • task1...string | function,需要按顺序执行的任务名或任务函数。
    • 返回:
    • tasksfunction,执行任务的函数。
  • gulp.parallel()(task1, task2, ...),并行执行任务。
    • task1...string | function,需要按顺序执行的任务名或任务函数。
    • 返回:
    • tasksfunction,执行任务的函数。

通常一个函数中能完成的任务是有限的(放到一个函数中也不方便代码的维护),所以我们会将任务进行组合。

gulp提供了两个强大的组合方法

  • series():串行任务组合。

  • parallel():并行任务组合。

image-20240229144224331

示例: 串行任务

image-20240907160506898

示例: 并行任务

image-20240907160917940

image-20240907160921223

文件操作

读取、写入文件

  • gulp.src()(glob, options?),读取文件并返回流。
    • globstring | string[],文件模式,支持 glob 匹配。
    • options?{base,cwd},可选配置,如 basecwd
    • 返回:
    • streamNodeJS.ReadWriteStream,读取流。
  • gulp.dest()(path, options?),将流写入目标目录。
    • pathstring,目标目录。
    • options?{base,cwd},可选配置,如 basecwd
    • 返回:
    • streamNodeJS.ReadWriteStream,可写流。
  • stream.pipe()(transform),将流传递给下一个处理步骤。常用于插件链式操作。
    • transformstream.Transform,变换流,如插件。

思路:

gulp 暴露了 src()dest() 方法用于处理计算机上存放的文件。

  • src() 接受参数,并从文件系统中读取文件然后生成一个 Node 流(Stream),它将所有匹配的文件读取到内存中并通过流(Stream)进行处理;

  • 由src() 产生的流(stream)应当从任务(task 函数)中返回并发出异步完成的信号;

  • dest() 接受一个输出目录作为参数,并且它还会产生一个 Node 流(stream),通过该流将内容输出到文件中;

流(stream)所提供的主要的 API 是 pipe() 方法,pipe 方法的原理是什么呢?

  • pipe 方法接受一个 转换流(Transform streams)或可写流(Writable streams);

  • 那么转换流或者可写流,拿到数据之后可以对数据进行处理,再次传递给下一个转换流或者可写流;

示例: 基本使用,拷贝单个js文件

image-20240907164016416

示例: 拷贝glob匹配到的多个js文件

image-20240907164217587

文件转换

依赖包:

  • gulp-babel:Gulp 插件,用于将 Babel 转换的功能集成到 Gulp 流程中。
    • 安装:pnpm i gulp-babel -D
  • gulp-terser:Gulp 插件,接收配置选项来控制压缩行为。
    • 安装:pnpm i gulp-terser -D

如果在这个过程中,我们希望对文件进行某些处理,可以使用社区给我们提供的插件。

  • 比如我们希望 ES6 转换成 ES5,那么可以使用 babel 插件;

  • 如果我们希望对代码进行压缩和丑化,那么可以使用 uglify 或者 terser 插件;

1、使用babel转化代码

image-20240907172011841

2、使用terser压缩、混淆代码

image-20240907173212280

文件监听

  • gulp.watch()(glob, tasks),监视文件变化并重新运行任务。
    • globstring | string[],监视的文件模式。
    • tasksstring | string[] | function,任务名或任务函数。
    • 返回:
    • gulp-watch:``,监视流。

gulp api中的 watch() 方法 利用文件系统的监控程序(file system watcher) 与之进行关联。

说明:当./src/**/*.js中的文件发生变化时,会重新运行jsTask任务打包项目

image-20240907173900674

案例:Gulp构建项目

依赖包:

  • gulp-htmlmin:是一个用于在使用 Gulp 构建工具时对 HTML 文件进行压缩的插件。它基于 html-minifier 库。
    • 安装:pnpm i gulp-htmlmin -D
  • gulp-less:是一个用于 Gulp 的 LESS 插件,主要用于将 LESS 文件编译成 CSS 文件。
    • 安装:pnpm i gulp-less -D
  • gulp-inject:是一个用于 Gulp 的插件,可以将样式表JavaScriptWeb 组件的引用注入到 HTML 文件中,避免手动编辑 index.html 文件。
    • 安装:pnpm i gulp-inject -D

接下来,我们编写一个案例,通过 gulp 来开启本地服务和打包:

1、打包html文件:gulp-htmlmin

注意: 配置项见:new HtmlWebpackPlugin({minify})

image-20240907213419472

image-20240907213444056

2、打包 JavaScript 文件:gulp-babelgulp-terser

image-20240908105005967

image-20240908105018698

3、打包 less 文件:gulp-less

image-20240908111046491

image-20240908111059569

4、将资源注入html:gulp-inject

  • 在html文件中添加占位

    image-20240908112009721

  • 添加inject任务

    image-20240908112156622

  • 注入效果

    image-20240908112055569

5、创建打包任务

  • 创建打包任务

    image-20240908112538097

  • 执行npx gulp finalTask开始打包

    image-20240908112634462

  • 打包效果

    image-20240908112654372

  • 问题: 打包后的引用路径有问题,不能写成绝对路径

    image-20240908113152460

    解决:在injectTask任务中,添加relative: true参数

    image-20240908113207597

    效果:

    image-20240908113303434

6、监听文件变化,重新构建项目

image-20240908114530683

7、开启本地服务器: browser-sync

注意: browser-sync 是第三方的插件,不是Gulp的插件

image-20240908115815393

运行脚本

  • 执行serveTask,开启本地服务

    sh
    npx gulp serveTask
  • package.json中编写scripts

    image-20240908120025773

    运行npm run buildnpm run serve

    sh
    # 执行打包任务
    npm run build
    
    # 运行本地服务器
    npm run serve

8、完整代码

image-20240229144427205

image-20240229144440243

库打包工具Rollup

概述

我们来看一下官方对 rollup 的定义:

  • Rollup is a module bundler for JavaScript which compiles small pieces of code into something larger and more complex,such as a library or application.

  • Rollup 是一个JS的模块化打包工具,可以帮助我们编译小的代码到一个大的、复杂的代码中,比如一个库或者一个应用程序。

Rollup VS Webpack:

我们会发现 Rollup 的定义、定位和 webpack 非常的相似

  • Rollup 也是一个模块化的打包工具,但是 Rollup主要是针对ES Module进行打包的;

  • webpack 通常可以通过各种 loader 处理各种各样的文件,以及处理它们的依赖关系;

    rollup 更多时候是专注于处理JS代码的(当然也可以处理 css、font、vue 等文件);

  • rollup 的配置和理念相对于 webpack 来说,更加的简洁和容易理解

  • 早期 webpack 不支持 tree shaking 时,rollup 具备更强的优势;

目前 webpack 和 rollup 分别有什么应用场景呢?

  • 通常在实际项目开发过程中,我们都会使用 webpack(比如 react、angular 项目都是基于 webpack 的);

  • 对库文件进行打包时,我们通常会使用 rollup(比如 vue、react、dayjs 源码本身都是基于 rollup 的,Vite 底层使用 Rollup);

Rollup基本使用

命令行语法

sh
npx rollup <file> -f iife -o <bundle>
  • <file>string,需要打包的文件。

  • -f <mode>iife | amd | cjs | umd,打包选项。

    • iife:打包浏览器的库
    • amd:打包 AMD 库
    • cjs:打包CommonJS 库
    • umd:打包通用库,需要跟上 --name
  • -o <bundle>string,指定打包后的输出目录。

  • sh
    # 打包浏览器的库 -f iife
    npx rollup ./src/main.js -f iife -o dist/bundle.js
    
    # 打包 AMD 的库 -f amd
    npx rollup ./src/main.js -f amd -o dist/bundle.js
    
    # 打包 CommonJS 的库 -f cjs
    npx rollup ./src/main.js -f cjs -o dist/bundle.js
    
    # 打包通用的库(必须跟上 name) -f umd --name mathUtil
    npx rollup ./src/main.js -f umd --name mathUtil -o dist/bundle.js

基本使用

1、安装 rollup:

sh
# 全局安装
npm install rollup -g

# 局部安装
npm install rollup -D

2、创建 lib/index.js 文件

image-20240908124606811

3、通过命令行打包

sh
npx rollup ./lib/index.js -o dist/bundle.js

4、打包时区分不同的环境

sh
# 打包浏览器的库 -f iife
npx rollup ./src/main.js -f iife -o dist/bundle.js

# 打包 AMD 的库 -f amd
npx rollup ./src/main.js -f amd -o dist/bundle.js

# 打包 CommonJS 的库 -f cjs
npx rollup ./src/main.js -f cjs -o dist/bundle.js

# 打包通用的库(必须跟上 name) -f umd --name mathUtil
npx rollup ./src/main.js -f umd --name mathUtil -o dist/bundle.js

5、通用环境时的打包结果

image-20240908141408359

配置文件

  • inputstring | string[],入口文件路径
  • output{file, format, name} | {file, format, name}[],输出配置,如文件路径、格式等。
    • filestring,打包输出文件名。
    • formatamd | cjs | iife | umd,打包环境格式,
      • amd:AMD格式
      • cjs :CommonJS格式
      • iife :立即执行函数,适用于浏览器环境
      • umd:通用环境格式(推荐)
    • namestring,全局名称。适用于iife和umd格式

1、将配置信息写到配置文件中 rollup.config.js 文件:

image-20240229144758817

2、可以对文件进行分别打包,打包出更多的库文件(用户可以根据不同的需求来引入):

image-20240229144807648

打包结果:

image-20240908213904892

常见插件

插件列表

解决CJS和第三方库问题

问题: 当项目中使用了第三方库(如lodash)时,由于lodash使用的是module.exports向外导出。而module.exports是commonjs的导出方式,rollup默认只会处理es module的语法。所欲lodash是不会被rollup打包的。

解决:需要安装额外的插件,让rollup支持打包commonjs语法。

1、安装解决 commonjs 的库:@rollup/plugin-commonjs

sh
npm install @rollup/plugin-commonjs -D

2、安装解析 node_modules 的库:@rollup/plugin-node-resolve

sh
npm install @rollup/plugin-node-resolve -D

3、配置插件

image-20240908215742427

4、实际开发中,库文件我们是不需要对lodash进行打包的,此时可以在配置中排除lodash打包

image-20240908215933963

Babel转换代码

如果我们希望将 ES6 转成 ES5 的代码,可以在 rollup 中使用 babel。

1、安装 rollup 对应的 babel 插件:@rollup/plugin-babel

sh
npm install @rollup/plugin-babel -D

2、修改配置文件:

  • 需要配置 babel.config.js 文件

    image-20240908220943941

  • babelHelpers

    image-20240908220935954

Teser代码压缩

如果我们希望对代码进行压缩,可以使用@rollup/plugin-terser

1、安装插件

sh
npm install @rollup/plugin-terser -D

2、配置terser

image-20240908221807666

image-20240908221841443

打包CSS

处理css文件

1、如果我们项目中需要处理 css 文件,可以使用 postcss

sh
npm install rollup-plugin-postcss postcss -D

2、配置 postcss 的插件

image-20240908224236132

3、打包效果

image-20240908224327864

4、为postcss添加 postcss-preset-env 配置

image-20240908224656575

image-20240908224740491

image-20240908224757478

打包Vue

处理vue文件

依赖包:

  • rollup-plugin-vue:``,
  • @vue/compiler-sfc:``,

1、处理 vue 文件我们需要使用 rollup-plugin-vue 插件

注意: 默认情况下我们安装的是 vue3.x 的版本,所以我这里指定了一下 rollup-plugin-vue 的版本;

sh
npm install rollup-plugin-vue @vue/compiler-sfc -D

2、使用vue的插件

image-20240229144934661

3、在我们打包 vue 项目后,运行会报如下的错误:

image-20240229144946029

这是因为在我们打包的 vue 代码中,用到 process.env.NODE_ENV,所以我们可以使用一个插件 @rollup/plugin-replace 设置它对应的值:

sh
npm install @rollup/plugin-replace -D

配置插件信息:

image-20240909165650216

本地服务器

依赖包:

  • rollup-plugin-serve:``,
  • rollup-plugin-livereload:``,

1、使用 rollup-plugin-serve 搭建服务

sh
npm install rollup-plugin-serve -D

image-20240229145040117

2、当文件发生变化时,自动刷新浏览器

sh
npm install rollup-plugin-livereload -D

image-20240229145045989

3、启动时,开启文件监听

sh
npx rollup -c -w

环境区分

1、在 package.json 中创建一个开发和构建的脚本:

image-20240909165226165

2、根据不同的环境,设置不同的配置项

image-20240909165558409

快速开发工具Vite

概述

认识Vite

什么是 vite 呢?

  • 官方的定位:下一代前端开发与构建工具

如何定义下一代开发和构建工具呢?

  • 我们知道在实际开发中,我们编写的代码往往是不能被浏览器直接识别的,比如 ES6、TypeScript、Vue 文件等等;

  • 所以我们必须通过构建工具来对代码进行转换、编译,类似的工具有 webpackrollupparcel

  • 但是随着项目越来越大,需要处理的 JavaScript 呈指数级增长,模块越来越多;

  • 构建工具需要很长的时间才能开启服务器,HMR 也需要几秒钟才能在浏览器反应出来;

  • 所以也有这样的说法:天下苦 webpack 久矣;

Vite (法语意为 "快速的",发音 /vit/) 是一种新型前端构建工具,能够显著提升前端开发体验。

image-20240229145339250

Vite构造

它主要由两部分组成

  • 一个开发服务器,它基于原生 ES 模块提供了丰富的内建功能,HMR 的速度非常快速;

  • 一套构建指令,它使用 rollup 打开我们的代码,并且它是预配置的,可以输出生产环境的优化过的静态资源;

在浏览器支持 ES 模块之前,JavaScript 并没有提供原生机制让开发者以模块化的方式进行开发。

  • 这也正是我们对 “打包” 这个概念熟悉的原因:使用工具抓取、处理并将我们的源码模块串联成可以在浏览器中运行的文件。

  • 时过境迁,我们见证了诸如 webpackRollupParcel等工具的变迁,它们极大地改善了前端开发者的开发体验。

  • 然而,当我们开始构建越来越大型的应用时,需要处理的 JavaScript 代码量也呈指数级增长。包含数千个模块的大型项目相当普遍。

  • 基于 JavaScript 开发的工具就会开始遇到性能瓶颈:通常需要很长时间(甚至是几分钟!)才能启动开发服务器,即使使用模块热替换(HMR),文件修改后的效果也需要几秒钟才能在浏览器中反映出来。

Vite 旨在利用生态系统中的新进展解决上述问题:

  • 浏览器开始原生支持 ES 模块,且越来越多 JavaScript 工具使用编译型语言编写。

  • the rise of JavaScript tools written in compile-to-native languages.

浏览器原生支持模块化

直接使用ES Module开发:

不借助于其他工具,直接使用 ES Module 来开发项目。

1、引入js脚本时,需要添加type="module"告诉浏览器当前JS是模块化代码

image-20240909173337225

2、在加载其他JS模块时不能省略后缀名

image-20240909173438879

3、如果项目中使用了第三方库(如lodash-es),需要如下引入

image-20240909174136747

直接使用ES Module开发的缺点:

但是如果我们不借助于其他工具,直接使用 ES Module 来开发有什么问题呢?

1、必须明确写上后缀名。

2、我们会发现在使用 loadash 时,加载了上百个模块的 js 代码,对于浏览器发送请求是巨大的消耗

3、我们的代码中如果有 TypeScript、less、vue 等代码时,浏览器并不能直接识别

事实上,vite 就帮助我们解决了上面的所有问题。

Vite优点

1、不需要添加后缀名

image-20240909175643229

2、加载第三方库不需要加载库内部引入的众多模块

image-20240909175931668

image-20240909175902669

3、增加了对TS、Vue、React的识别支持

image-20240909180541140

Vite打包

Vite安装

1、我们安装一下vite工具

sh
npm install vite –g

# 局部安装(推荐)
npm install vite -D

2、通过vite来启动项目

sh
npx vite

Vite对css的支持

1、vite 可以直接支持 css 的处理

  • 直接导入 css 即可;

2、vite 可以直接支持 css 预处理器,比如 less

  • 直接导入 less;

  • 之后安装 less 编译器;

sh
npm install less -D

3、vite 直接支持 postcss 的转换:

  • 只需要安装 postcss,并且配置 postcss.config.js 的配置文件即可;
sh
npm install postcss postcss-preset-env -D

image-20240909181021009

image-20240909181051226

Vite对TypeScript的支持

vite 对 TypeScript 是原生支持的,它会直接使用 ESBuild 来完成编译,只需要直接导入即可。

如果我们查看浏览器中的请求,会发现请求的依然是 ts 的代码:

  • 这是因为 vite 中的服务器 Connect 会对我们的请求进行转发;

  • 获取 ts 编译后的代码,给浏览器返回,浏览器可以直接进行解析;

  • 虽然请求的是TS文件,但是内容已经是转化后的JS代码了

    image-20240910092226580

注意: 在 vite2 中,已经不再使用 Koa 了,而是使用 Connect 来搭建的服务器。这是因为vite中主要的都是请求转发业务,没有必要使用Koa。

image-20240910092847322

Vite对vue的支持

vite 对 vue 提供第一优先级支持:

1、安装支持vue的插件:

sh
npm install @vitejs/plugin-vue -D

2、在 vite.config.js 中配置插件:(配置的写法和rollup相似)

image-20240910094215402

image-20240910094412236

Vite对react的支持

.jsx 和 .tsx 文件同样开箱即用,它们也是通过 ESBuild 来完成的编译:

所以我们只需要直接编写 react 的代码即可;

image-20240229145549082

image-20240229145559776

注意: 在 index.html 加载 main.js 时,我们需要将 main.js 的后缀,修改为 main.jsx 作为后缀名;

image-20240910095335858

Vite打包项目

1、我们可以直接通过 vite build 来完成对当前项目的打包工具:

sh
npx vite build

image-20240910095838445

2、我们可以通过 vite preview 的方式,开启一个本地服务来预览打包后的效果

sh
npx vite preview

注意: vite打包底层是使用的Rollup

image-20240910100112494

Vite脚手架工具

Vite脚手架create-vite

在开发中,我们不可能所有的项目都使用 vite 从零去搭建,比如一个 react 项目、Vue 项目;

  • 这个时候 vite 还给我们提供了对应的脚手架工具;

所以 Vite 实际上是有两个工具的:

  • vite:构件工具。类似于 webpack、rollup;

  • create-vite:vite的脚手架工具。类似 vue-cli、create-react-app;

如果使用脚手架工具呢?

sh
npm create vite

yarn create vite

pnpm create vite

image-20240910102643099

image-20240910103026758

EsBuild

ESBuild解析

ESBuild 的特点

  • 超快的构建速度,并且不需要缓存;

  • 支持 ES6 和 CommonJS 的模块化;

  • 支持 ES6 的 Tree Shaking;

  • 支持 Go、JavaScript 的 API;

  • 支持 TypeScript、JSX 等语法编译;

  • 支持 SourceMap;

  • 支持代码压缩;

  • 支持扩展其他插件;

ESBuild的构建速度

ESBuild 的构建速度和其他构建工具速度对比:

image-20240229145637822

ESBuild 为什么这么快呢?

  • 使用 Go 语言编写的,可以直接转换成机器代码,而无需经过字节码;

  • ESBuild 可以充分利用CPU的多内核,尽可能让它们饱和运行;

  • ESBuild 的所有内容都是从零开始编写的,而不是使用第三方,所以从一开始就可以考虑各种性能问题;

  • 等等....